package com.fept.msgcore.msgserver.netty.server;

/**
 * Created by Srma on 1/12/2017.
 */


import com.fept.msgcore.msgserver.netty.channel.ChannelManager;
import com.fept.msgcore.msgserver.netty.handler.BaseMessageHandlerFactory;
import com.fept.msgcore.msgserver.netty.handler.DecoderFactory;
import com.fept.msgcore.msgserver.netty.handler.EncoderFactory;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelOption;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

public class NettyServer {
    private static Logger logger = LoggerFactory.getLogger(NettyServer.class);

    private int port = 0;
    private EventLoopGroup bossGroup = new NioEventLoopGroup();
    private EventLoopGroup workerGroup = new NioEventLoopGroup();
    private ServerBootstrap bootStrap;
    private String serverName = "";
    private static Map<String, NettyServer> nettyServers = new ConcurrentHashMap();

    public static NettyServer createNettyServer(String name, int port, EncoderFactory ef, DecoderFactory df, BaseMessageHandlerFactory bf) {
        NettyServer server = (NettyServer)nettyServers.get(name);
        if(server != null) {
            logger.error("Netty server " + name + " already running!");
            return null;
        } else {
            server = new NettyServer(name, port, ef, df, bf);
            nettyServers.put(name, server);
            return server;
        }
    }

    public void shutdown() {
        this.workerGroup.shutdownGracefully();
    }

    public void start() {
        (new Thread() {
            public void run() {
                try {
                    NettyServer.logger.info("Start server " + NettyServer.this.getServerName() + ": listening on " + NettyServer.this.port + "!");
                    NettyServer.this.run();
                    NettyServer.logger.info("Stop server " + NettyServer.this.getServerName() + ": stop listening on " + NettyServer.this.port + "!");
                } catch (InterruptedException var2) {
                    NettyServer.logger.info("Server " + NettyServer.this.getServerName() + " failed with exception " + var2.getMessage() + "!");
                }

            }
        }).start();
    }

    private NettyServer(String name, int port, EncoderFactory ef, DecoderFactory df, BaseMessageHandlerFactory bf) {
        this.setServerName(name);
        this.port = port;
        ChannelManager.getChannelManager(this.serverName);
        this.bootStrap = new ServerBootstrap();
        this.bootStrap.option(ChannelOption.TCP_NODELAY, Boolean.valueOf(true));
        this.bootStrap.option(ChannelOption.SO_KEEPALIVE, Boolean.valueOf(true));
        ((ServerBootstrap)this.bootStrap.group(this.bossGroup, this.workerGroup).channel(NioServerSocketChannel.class)).childHandler(new NettyServerInitializer(this.serverName, ef, df, bf));
    }

    public void clean() {
        this.bossGroup.shutdownGracefully();
        this.workerGroup.shutdownGracefully();
    }

    public void run() throws InterruptedException {
        this.bootStrap.bind(this.port).sync().channel().closeFuture().sync();
    }

    public String getServerName() {
        return this.serverName;
    }

    public void setServerName(String serverName) {
        this.serverName = serverName;
    }

}
